# coding:utf-8
import uuid
import os
from datetime import datetime
from flask import request, g, jsonify, send_from_directory
from flask_jwt_extended import jwt_required, current_user
import flask_excel as excel
from sqlalchemy import asc, desc, true
from werkzeug.utils import secure_filename
from myapp.routes import system
from myapp import db, setup_logger
from ... import captcha
from myapp.models import User, Organization, Role, OnLine, SysConfig
from myapp.utils.auth import (
    authenticate,
    create_tokens,
    refresh_access_token,
    permission
)
from myapp.utils.reposeUtils import ApiResponse
from ...operationlog import log_operation
logger = setup_logger(__name__)

@permission('system:role:edit')
@system.route('/user/authRole', methods=['PUT'])
@jwt_required()
def grant_user_role():
    id = request.args['userId']
    ids = request.args['roleIds']

    user = User.query.get(id)

    if not ids:
        user.roles = []
    else:
        idList = ids.split(',')
        user.roles = [Role.query.get(rid) for rid in idList]

    db.session.add(user)

    return jsonify({'code': 200, 'msg': '操作成功'})

@jwt_required()
def record_login_history(type):
    online = OnLine()
    online.id = str(uuid.uuid4())
    online.login_name = current_user.login_name
    online.ip = request.remote_addr
    online.type = type
    db.session.add(online)

# 直接删除前端token即可，默认多点在线，单点登录实现请先接入数据库或者缓存，存储token
# @system.route('/logout', methods=['POST'])
# @jwt_required()
# def do_logout():
#     record_login_history(0)
#     # 需手动实现logout_user逻辑
#     return jsonify({'msg': 'success', 'code': 200})

@system.route('/login', methods=['POST'])
def do_login():
    try:
        username = request.json['username']
        password = request.json['password']
        uuid = request.json['uuid']
        verifyCode = request.json['verifyCode']
        # 验证码检查（测试可注释）
        config = SysConfig.query.filter(SysConfig.config_key == 'sys.account.captchaOnOff').first()
        if config and config.config_value == 'true':
            if not captcha.verify(verifyCode.upper(),uuid):
                logger.error("验证码错误：username:"+username+' uuid:'+uuid+' verifyCode:'+verifyCode)
                return ApiResponse.error(msg='验证码错误', code=400)

        # 检查用户是否存在
        user = User.query.filter_by(login_name=username).first()
        if not user:
            logger.error("用户不存在：username:" + username + ' uuid:' + uuid + ' verifyCode:' + verifyCode)
            return ApiResponse.error(msg='用户不存在', code=400)

        # 检查账号状态
        if user.status != '0':
            logger.error("账号未激活：username:" + username + ' uuid:' + uuid + ' verifyCode:' + verifyCode)
            return ApiResponse.error(msg='账号未激活，请联系管理员', code=400)

        # 验证密码
        if not authenticate(username, password):
            logger.error("账号或密码错误：username:" + username + ' uuid:' + uuid + ' verifyCode:' + verifyCode)
            return ApiResponse.error(msg='账号或密码错误', code=400)

        # 生成令牌
        tokens = create_tokens(user)

        # 构建响应数据（确保所有数据可序列化）
        data = {
            'avatar': user.photo or '',  # 处理可能的None值
            'username': user.login_name,
            'nickname': user.name,
            'roles': [role.role_key for role in user.roles],  # 转换为可序列化的列表
            **tokens  # 展开令牌
        }

        return ApiResponse.success(msg="登录成功",data=data)

    except Exception as e:
        log_username = username if 'username' in locals() else 'N/A'
        log_uuid = uuid if 'uuid' in locals() else 'N/A'
        log_verifyCode = verifyCode if 'verifyCode' in locals() else 'N/A'
        logger.error(
            f"登录异常 username:{log_username} "
            f"uuid:{log_uuid} "
            f"verifyCode:{log_verifyCode}",
            exc_info=True
        )
        return ApiResponse.server_error(msg='登录异常')

@system.route('/refresh-token', methods=['POST'])
# @jwt_required(refresh=True)
def refresh():
    refreshToken = request.json.get('refreshToken')
    data = {"refreshToken": refreshToken, **refresh_access_token()}
    return ApiResponse.success(data=data)

@system.route('/fresh-login', methods=['POST'])
def fresh_login():
    """获取新鲜Token（用于敏感操作）"""
    user = authenticate(request.json.get('username'), request.json.get('password'))
    if not user:
        return jsonify({"msg": "Bad credentials"}), 401
    # 创建新鲜Token（fresh=True）
    access_token = create_tokens(user)
    return jsonify(access_token=access_token)

@permission('system:user:list')
@system.route('/user/list', methods=['GET'])
@jwt_required()
def user_grid():
    filters = []
    if 'username' in request.args:
        filters.append(User.login_name.like('%' + request.args['username'] + '%'))
    if 'phoneNumber' in request.args:
        filters.append(User.phone_number.like('%' + request.args['phoneNumber'] + '%'))
    if 'params[beginTime]' in request.args and 'params[endTime]' in request.args:
        filters.append(User.create_time >  request.args['params[beginTime]'])
        filters.append(User.create_time <  request.args['params[endTime]'])

    order_by = []
    if request.form.get('sort'):
        if request.form.get('order') == 'asc':
            order_by.append(asc(getattr(User,request.form.get('sort').upper())))
        elif request.form.get('order') == 'desc':
            order_by.append(desc(getattr(User,request.form.get('sort').upper())))
        else:
            order_by.append(getattr(User,request.form.get('sort').upper()))

    page = request.args.get('pageNum', 1, type=int)
    rows = request.args.get('pageSize', 10, type=int)
    if 'deptId' in request.args:
        # Define a recursive CTE
        dept_cte = (
            db.session.query(Organization.ID)
            .filter(Organization.ID == request.args['deptId'])
            .cte('dept_tree', recursive=True)
        )
        
        # Recursive part of the CTE
        dept_cte = dept_cte.union_all(
            db.session.query(Organization.ID)
            .join(dept_cte, Organization.SYORGANIZATION_ID == dept_cte.c.ID)
        )
        pagination = User.query.join(Organization, User.organizations).join(
            dept_cte, Organization.ID == dept_cte.c.ID).filter(*filters).params(
            dept_id=request.args['deptId']).order_by(*order_by).paginate(
            page=page, per_page=rows, error_out=False)
    else:
        pagination = User.query.filter(*filters).order_by(*order_by).paginate(
            page=page, per_page=rows, error_out=False)
    users = pagination.items

    return jsonify({'rows': [user.to_json() for user in users], 'total': pagination.total, 'code': 200, 'msg': '查询成功'})

@system.route('/user/', methods=['GET'])
@jwt_required()
def syuser_get():
    json = {'code': 200, 'msg': ''}
    json['roles'] = [role.to_json() for role in Role.query.all()]
    json['posts'] = []
    return jsonify(json)

@permission('system:user:query')
@system.route('/user/<id>', methods=['GET'])
@jwt_required()
def syuser_getById(id):
    user = User.query.get(id)

    if user:
        json = {'code': 200, 'msg': '', 'data': user.to_json()}
        if len(user.roles.all()) > 0:
            json['roles'] = [role.to_json() for role in user.roles]
            json['roleIds'] = [role.ID for role in user.roles]

        return jsonify(json)
    else:
        return jsonify({'success': False, 'msg': 'error'})

@permission('system:user:edit')
@system.route('/user', methods=['PUT'])
@jwt_required()
def syuser_update():
    id = request.json['userId']
    username = request.json['username']
    
    # if User.query.filter(User.login_name == login_name).filter(User.id != id).first():
    #     return jsonify({'code': 201, 'msg': '更新用户失败，用户名已存在！'})

    user = User.query.get(id)

    user.update_time = datetime.now()
    if 'nickname' in request.json: user.name = request.json['nickname'] 
    if 'sex' in request.json: user.sex = request.json['sex']
    if 'email' in request.json: user.email = request.json['email']
    if 'phoneNumber' in request.json: user.phone_number = request.json['phoneNumber']
    if 'deptId' in request.json: user.organizations = Organization.query.filter(Organization.ID == request.json['deptId']).all()
    if 'roleIds' in request.json:
        user.roles = [Role.query.get(roleId) for roleId in request.json['roleIds']]

    db.session.add(user)

    return jsonify({'code': 200, 'msg': '更新成功！'})

@permission('system:user:add')
@system.route('/user', methods=['POST'])
@jwt_required()
def syuser_save():
    if User.query.filter_by(login_name = request.json['username']).first():
        return jsonify({'success': False, 'msg': '新建用户失败，用户名已存在！'})

    user = User()
    user.id = str(uuid.uuid4())
    user.set_password(request.json['password'])

    with db.session.no_autoflush:
        if 'nickname' in request.json: user.name = request.json['nickname'] 
        if 'sex' in request.json: user.sex = request.json['sex']
        if 'email' in request.json: user.email = request.json['email']
        if 'phoneNumber' in request.json: user.phone_number = request.json['phoneNumber']
        if 'deptId' in request.json: user.organizations = Organization.query.filter(Organization.ID == request.json['deptId']).all()
        if 'roleIds' in request.json:
            user.roles = [Role.query.get(roleId) for roleId in request.json['roleIds']]

        user.login_name = request.json['username']

        # add current use to new user
        #current_user.roles.append(user)

        db.session.add(user)

    return jsonify({'code': 200, 'msg': '新建用户成功！'})

@system.route('/register', methods=['POST'])
def syuser_register():
    if User.query.filter_by(login_name = request.json['username']).first():
        return jsonify({'success': False, 'msg': '注册用户失败，用户名已存在！'})

    user = User()
    user.id = str(uuid.uuid4())
    user.set_password(request.json['password'])

    with db.session.no_autoflush:
        user.name = request.json['username']
        user.roles = Role.query.filter(Role.name == '只读用户').all()

        user.login_name = request.json['username']
        user.name = user.login_name
        user.status = '0'

        db.session.add(user)
        db.session.commit()

    return jsonify({'code': 200, 'msg': '注册用户成功！'})

@permission('system:user:remove')
@system.route('/user/<id>', methods=['DELETE'])
@jwt_required()
def syuser_delete(id):
    user = User.query.get(id)
    if user:
        db.session.delete(user)

    return jsonify({'code': 200, 'msg': '删除成功'})

@jwt_required(fresh=True)
@log_operation('修改密码')
@system.route('/user/profile/updatePwd', methods=['PUT'])
def syuser_update_pwd():
    user = User.query.get(current_user.id)

    if user.check_password(request.args.get('oldPassword')):
        user.set_password(request.args.get('newPassword'))
        db.session.add(user)
        return jsonify({'code': 200, 'msg': '修改成功'})
    else:
        return jsonify({'code': 400, 'msg': '旧密码错误'})

@system.route('/getInfo', methods=['GET'])
@jwt_required()
def syuser_info():
    try:
        # 1. 获取用户基本信息
        user_info = {
            'avatar': current_user.photo if hasattr(current_user, 'photo') else '',
            'username': current_user.login_name,
            'nickname': current_user.name,
            'email': current_user.email if hasattr(current_user, 'email') else None,
            'phone': current_user.phone_number if hasattr(current_user, 'phone_number') else None,
            'description': current_user.description if hasattr(current_user, 'description') else None,
            'userId': current_user.id,
        }

        # 2. 获取用户角色
        # roles = [role.name for role in current_user.roles]

        # 3. 获取用户权限（合并组织和角色的权限，自动去重）
        # permissions = set()
        # permission_codes = set()

        # 从组织获取资源
        # for org in current_user.organizations:
        #     if org.resources:
        #         for res in org.resources:
        #             permissions.add(res)
        #             if res.perms:  # 假设perms是权限标识
        #                 permission_codes.add(res.perms)

        # 从角色获取资源
        # for role in current_user.roles:
        #     if role.resources:
        #         for res in role.resources:
        #             permissions.add(res)
        #             if res.perms:
        #                 permission_codes.add(res.perms)

        # 4. 构建响应数据
        # response_data = {
        #     'user': user_info,
            # 'roles': roles,
            # 'permissions': [res.to_json() for res in permissions],
            # 'permissionCodes': list(permission_codes)  # 单独返回权限标识列表
        # }

        return ApiResponse.success(msg='获取用户信息成功',data=user_info)

    except Exception as e:
        logger.error(f"获取用户信息失败: {str(e)}")
        return ApiResponse.error(msg='获取用户信息失败')

@system.route('/user/profile', methods=['GET'])
@jwt_required()
def syuser_profile():
     return jsonify({'msg': '操作成功', 'code': 200, \
        'data': current_user.to_json(), \
        'postGroup': current_user.organizations[0].name if len(current_user.organizations) > 0 else '', \
        'roleGroup': [role.name for role in current_user.roles]})

@system.route('/user/profile', methods=['PUT'])
@jwt_required()
def syuser_update_profile():
    id = request.json['userId']
    username = request.json['username']
    user = User.query.get(id)

    user.UPDATEDATETIME = datetime.now()
    if 'nickname' in request.json: user.name = request.json['nickname']
    if 'sex' in request.json: user.sex = request.json['sex']
    if 'email' in request.json: user.email = request.json['email']
    if 'phoneNumber' in request.json: user.phone_number = request.json['phoneNumber']

    db.session.add(user)

    return jsonify({'code': 200, 'msg': '更新成功！'})

@system.route('/user/authRole/<id>', methods=['GET'])
@jwt_required()
def syuser_auth_role(id):
    user = User.query.get(id)
    userRoles = [role for role in user.roles]
    allRoles = Role.query.all()
    for allRole in allRoles:
        for userRole in userRoles:
            if userRole.ID == allRole.ID:
                allRole.flag = True

    return jsonify({'code': 200, 'msg': '操作成功', 'roles': [role.to_json() for role in allRoles], 'user': user.to_json()})

@system.route('/base/syuser/export', methods=['POST'])
@jwt_required()
def user_export():
    rows = []
    rows.append(['登录名', '姓名', '创建时间', '修改时间', '性别'])

    users = User.query.all()
    for user in users:
        row = []
        row.append(user.login_name)
        row.append(user.name)
        row.append(user.create_time)
        row.append(user.update_time)
        if user.SEX == '0':
            row.append('女')
        elif user.SEX == '1':
            row.append('男')
        rows.append(row)

    return excel.make_response_from_array(rows, "csv", file_name="user")

@permission('system:user:edit')
@system.route('/user/changeStatus', methods=['PUT'])
@jwt_required()
def syuser_status_update():
    user = User.query.get(request.json['userId'])

    if 'status' in request.json: user.STATUS = request.json['status']

    db.session.add(user)

    return jsonify({'code': 200, 'msg': '操作成功'})

@system.route('/user/profile/avatar', methods=['POST'])
@jwt_required()
def syuser_avatar_update():
    try:
        # 1. 检查文件上传
        if 'avatarFile' not in request.files:
            return jsonify({'msg': '未上传文件', 'code': 400}), 400

        file = request.files['avatarFile']
        if file.filename == '':
            return jsonify({'msg': '空文件', 'code': 400}), 400

        # 2. 验证文件类型
        allowed_extensions = {'jpg', 'jpeg', 'png', 'gif'}
        filename = secure_filename(file.filename)
        if '.' not in filename or filename.rsplit('.', 1)[1].lower() not in allowed_extensions:
            return jsonify({'msg': '只允许上传图片文件(jpg,jpeg,png,gif)', 'code': 400}), 400

        # 3. 生成新文件名
        ext = filename.rsplit('.', 1)[1].lower()
        new_filename = f"{uuid.uuid4()}.{ext}"
        upload_path = get_upload_path()
        new_filepath = os.path.join(upload_path, new_filename)

        # 4. 删除旧头像文件（如果存在）
        if current_user.photo:
            try:
                old_filepath = os.path.join(upload_path, os.path.basename(current_user.photo))
                if os.path.exists(old_filepath):
                    os.remove(old_filepath)
            except Exception as e:
                logger.error(f"删除旧头像失败: {str(e)}")

        # 5. 保存新文件
        file.save(new_filepath)

        # 6. 更新数据库
        avatar_url = f'/system/user/profile/avatar/{new_filename}'
        current_user.photo = avatar_url
        db.session.commit()

        return jsonify({ 'msg': '头像更新成功', 'code': 200, 'imgUrl': avatar_url })

    except Exception as e:
        db.session.rollback()
        logger.error(f"头像更新失败: {str(e)}")
        return jsonify({
            'msg': '头像更新失败',
            'code': 500
        }), 500

@system.route('/user/profile/avatar/<filename>', methods=['GET'])
@jwt_required()
def sysuser_avatar_preview(filename):
    try:
        filename = secure_filename(filename)
        response = send_from_directory(get_upload_path(), filename, as_attachment=False)
            # 根据文件扩展名设置 MIME 类型
        if filename.endswith('.jpg') or filename.endswith('.jpeg'):
            response.headers['Content-Type'] = 'image/jpeg'
        elif filename.endswith('.png'):
            response.headers['Content-Type'] = 'image/png'
        return response
    except FileNotFoundError: 
        return jsonify({'msg': '文件不存在', 'code': 404})

def get_upload_path():
    parent = os.path.dirname(os.path.abspath(__file__))
    parent = os.path.dirname(parent)
    parent = os.path.dirname(parent)

    path = os.path.join(parent, "uploads")
    if not os.path.exists(path):
        os.makedirs(path)
    return path
